package com.haixiaoke.saas.bill.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.haixiaoke.saas.bill.domain.Bill;
import com.haixiaoke.saas.bill.domain.BillItem;
import com.haixiaoke.saas.bill.mapper.BillMapper;
import com.haixiaoke.saas.bill.service.IBillItemService;
import com.haixiaoke.saas.bill.service.IBillService;
import com.haixiaoke.saas.common.config.WeChatConfig;
import com.haixiaoke.saas.common.constant.BillConstants;
import com.haixiaoke.saas.common.constant.ContractConstants;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.common.weChat.domain.ParseParam;
import com.haixiaoke.saas.common.weChat.domain.UnifiedOrder;
import com.haixiaoke.saas.common.weChat.service.WeChatService;
import com.haixiaoke.saas.contract.domain.Contract;
import com.haixiaoke.saas.contract.service.IContractService;
import com.haixiaoke.saas.user.domain.UserConsumer;
import com.haixiaoke.saas.user.service.IUserConsumerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 账单Service业务层处理
 *
 * @author panda
 * @date 2025-06-26
 */
@Slf4j
@Service
public class BillServiceImpl implements IBillService {
    @Autowired
    private BillMapper billMapper;
    @Autowired
    private IContractService contractService;
    @Autowired
    private IBillItemService billItemService;
    @Autowired
    private IUserConsumerService userConsumerService;
    @Autowired
    private WeChatConfig weChatConfig;
    @Autowired
    private WeChatService weChatService;

    /**
     * 查询账单
     *
     * @param billId 账单主键
     * @return 账单
     */
    @Override
    public Bill selectBillByBillId(String billId) {
        Bill bill = billMapper.selectBillByBillId(billId);
        if (ObjectUtil.isNotEmpty(bill)) {
            List<BillItem> billItemList = billItemService.selectBillItemByBillId(billId);
            bill.setBillItemList(billItemList);
        }
        return bill;
    }

    /**
     * 查询账单列表
     *
     * @param bill 账单
     * @return 账单
     */
    @Override
    public List<Bill> selectBillList(Bill bill) {
        return billMapper.selectBillList(bill);
    }

    /**
     * 新增账单
     *
     * @param bill 账单
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult insertBill(Bill bill) {
        if (StrUtil.isBlank(bill.getContractId())) {
            return AjaxResult.error("请选择合同");
        }
        if (CollectionUtil.isEmpty(bill.getBillItemList())) {
            return AjaxResult.error("账单收费项异常");
        }
        boolean repeatResult = bill.getBillItemList().stream()
                .collect(Collectors.groupingBy(BillItem::getItemName))
                .values()
                .stream()
                .anyMatch(group -> group.size() > 1);
        if (repeatResult) {
            return AjaxResult.error("账单收费项名称不能重复");
        }
        boolean hasNullAmount = bill.getBillItemList().stream()
                .map(BillItem::getItemAmount)
                .anyMatch(Objects::isNull);
        if (hasNullAmount) {
            return AjaxResult.error("账单收费项金额不能为空");
        }
        List<BigDecimal> itemPrices = bill.getBillItemList().stream().map(BillItem::getItemAmount).filter(itemPrice -> itemPrice.compareTo(BigDecimal.ZERO) <= 0).collect(Collectors.toList());
        if (!itemPrices.isEmpty()) {
            return AjaxResult.error("费用价格只能大于0");
        }
        List<BigDecimal> scalePrices = bill.getBillItemList().stream().map(BillItem::getItemAmount).filter(itemPrice -> itemPrice.scale() > 2).collect(Collectors.toList());
        if (!scalePrices.isEmpty()) {
            return AjaxResult.error("费用价格最多两位小数");
        }

        Contract contract = contractService.selectContractByContractId(bill.getContractId());
        if (ObjectUtil.isEmpty(contract)) {
            return AjaxResult.error("合同不存在");
        }
        //只有已入住才能新增账单
        if (!StrUtil.equals(ContractConstants.CONTRACT_STATE_CHECK_IN, contract.getContractState())) {
            return AjaxResult.error("合同状态不正确");
        }

        String billId = "B" + System.currentTimeMillis() + RandomUtils.nextInt(10000, 100000);

        BigDecimal total = BigDecimal.ZERO;
        for (BillItem billItem : bill.getBillItemList()) {
            billItem.setBillId(billId);
            total = total.add(billItem.getItemAmount());
        }
        billItemService.insertBatchBillItem(bill.getBillItemList());
        bill.setBillId(billId);
        bill.setBillAmount(total);
        bill.setCreateTime(DateUtils.getNowDate());
        bill.setBillState(BillConstants.BILL_STATE_UNPAID);
        bill.setConUserId(contract.getConUserId());
        int result = billMapper.insertBill(bill);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 修改账单
     *
     * @param bill 账单
     * @return 结果
     */
    @Override
    public int updateBill(Bill bill) {
        bill.setUpdateTime(DateUtils.getNowDate());
        return billMapper.updateBill(bill);
    }

    /**
     * 批量删除账单
     *
     * @param billIds 需要删除的账单主键
     * @return 结果
     */
    @Override
    public int deleteBillByBillIds(String[] billIds) {
        return billMapper.deleteBillByBillIds(billIds);
    }

    /**
     * 删除账单信息
     *
     * @param billId 账单主键
     * @return 结果
     */
    @Override
    public int deleteBillByBillId(String billId) {
        return billMapper.deleteBillByBillId(billId);
    }

    @Override
    public AjaxResult completed(Bill bill) {
        if (CollectionUtil.isEmpty(bill.getPayVoucherList()) || bill.getPayVoucherList().size() > 6) {
            return AjaxResult.error("付款凭证图片异常");
        }
        Bill billByBillId = billMapper.selectBillByBillId(bill.getBillId());
        if (ObjectUtil.isEmpty(billByBillId)) {
            return AjaxResult.error("账单不存在");
        }
        if (!StrUtil.equals(BillConstants.BILL_STATE_UNPAID, billByBillId.getBillState())) {
            return AjaxResult.error("只有未付款账单才能完成");
        }
        Date nowDate = DateUtils.getNowDate();
        bill.setUpdateTime(nowDate);
        bill.setPayVoucher(StringUtils.join(bill.getPayVoucherList(), ","));
        bill.setBillState(BillConstants.BILL_STATE_PAID);
        bill.setPayDate(nowDate);
        int result = billMapper.updateBill(bill);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult cancel(String billId, String username) {
        Bill bill = billMapper.selectBillByBillId(billId);
        if (ObjectUtil.isEmpty(bill)) {
            return AjaxResult.error("账单不存在");
        }
        if (!StrUtil.equals(BillConstants.BILL_STATE_UNPAID, bill.getBillState())) {
            return AjaxResult.error("只有未付款账单才能取消");
        }
        bill.setBillState(BillConstants.BILL_STATE_CANCELED);
        bill.setUpdateTime(DateUtils.getNowDate());
        bill.setUpdateBy(username);
        int result = billMapper.updateBill(bill);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult payBill(String billId, Long userId, String payType) {
        Bill bill = billMapper.selectBillByBillId(billId);
        if (ObjectUtil.isEmpty(bill)) {
            return AjaxResult.error("账单不存在");
        }
        if (!StrUtil.equals(BillConstants.BILL_STATE_UNPAID, bill.getBillState())) {
            return AjaxResult.error("该账单无需付款");
        }
        UserConsumer userConsumer = userConsumerService.selectUserConsumerByUserId(userId);
        if (ObjectUtil.isEmpty(userConsumer) || StrUtil.isBlank(userConsumer.getOpenId())) {
            return AjaxResult.error("用户信息过期，请重新登录");
        }
        UnifiedOrder unifiedOrder = new UnifiedOrder();
        unifiedOrder.setOpenId(userConsumer.getOpenId());
        unifiedOrder.setAppId(weChatConfig.getAppId());
        unifiedOrder.setAccountId(weChatConfig.getAccountId());
        unifiedOrder.setAccountApiKey(weChatConfig.getAccountApiKey());
        //unifiedOrder.setAttach();
        unifiedOrder.setOutTradeNo(bill.getBillId());
        BigDecimal totalFee = bill.getBillAmount();
        unifiedOrder.setCallBackUrl(weChatConfig.getBillPayCallBackUrl());
        unifiedOrder.setBody("房屋管理-账单微信支付");
        unifiedOrder.setTotalFee(totalFee.multiply(BigDecimal.valueOf(100)).intValue());
        AjaxResult ajaxResult = AjaxResult.error();
        if (StrUtil.equals(BillConstants.PAYMENT_TYPE_WECHAT, payType)) {
            ajaxResult = weChatService.unifiedOrder(unifiedOrder);
        } else if (StrUtil.equals(BillConstants.PAYMENT_TYPE_SCAN, payType)) {
            ajaxResult = weChatService.nativeOrder(unifiedOrder);
        }
        return ajaxResult;
    }

    @Override
    public void weChatCallbackBillPay(ParseParam parseParam) {
        Bill bill = billMapper.selectBillByBillId(parseParam.getOutTradeNo());
        if (ObjectUtil.isEmpty(bill)) {
            log.error("查询不到账单,参数：{}", JSONObject.toJSONString(parseParam));
            return;
        }
        if (!StrUtil.equals(BillConstants.BILL_STATE_UNPAID, bill.getBillState())) {
            log.error("账单状态不正确,参数：{}", JSONObject.toJSONString(parseParam));
            return;
        }
        Date nowDate = DateUtils.getNowDate();
        bill.setBillState(BillConstants.BILL_STATE_PAID);
        bill.setUpdateTime(nowDate);
        bill.setPayDate(nowDate);
        billMapper.updateBill(bill);
    }

    @Override
    public List<Map<String, Object>> homePage() {
        return billMapper.homePage();
    }
}